const router = require('koa-router')();

const https = require('https');
const axios = require('axios')
const dayjs = require('dayjs');
const urlencode = require('urlencode')

const script = require('./scripts/capitaland');
const configs = require('./scripts/capitalandWebApis.json');

router.prefix('/api/iworkflow');

router.get('/webapi/hosts', async (ctx, next) => {
    await (ctx.body = configs.hosts);
});

router.get('/webapi/configs', async (ctx, next) => {
    let apis = JSON.parse(JSON.stringify(configs.apis));

    apis.forEach(item => {
        if (item.paramsRef) {
            item.params = item.params || [];

            item.params.unshift(...configs.params[item.paramsRef]);
        } else {
            item.params = item.params || [];
        }
    });

    await (ctx.body = {
        hosts: configs.hosts,
        defines: configs.defines,
        apis: apis
    });
});

router.post('/webapi/invoke', async (ctx, next) => {
    let jsonValue = JSON.parse(ctx.request.body.__jsonValue__ || '{}') || {};

    let host = jsonValue.host || ctx.request.body.host;
    let api = jsonValue.api || ctx.request.body.api;

    let rs = {
        at: dayjs().format("YYYY-MM-DD HH:mm:ss"),
        success: false
    };

    let config = getApiConfig(api);

    if (!config) {
        config = {
            method: jsonValue.method || 'get'
        };
    }

    try {
        let data = ctx.request.body.data || jsonValue.data || [];
        let responseType = data.find(d => (d.name || '').toLowerCase() == 'isexport' && d.type == 'query' && d.value == 'true') ? 'stream' : 'json';

        let response = await axios({
            method: config.method,
            headers: { 'content-type': 'application/x-www-form-urlencoded', 'Cache-Control': 'no-cache' },
            url: `${host}${api}?AppID=${configs.auth.appId}&AppSecret=${configs.auth.appSecret}${resolveParams(data)}`,
            data: resolveBody(data),
            responseType: responseType,
            httpsAgent: new https.Agent({
                rejectUnauthorized: false
            })
        });

        if (response.headers['content-type'] == 'application/octet-stream') {
            ctx.type = 'application/octet-stream';

            // 设置下载文件名
            ctx.attachment(decodeURI(response.headers.filename));
            ctx.body = response.data;

            return;
        }

        rs.success = true;
        rs.result = response.data;
    } catch (err) {
        rs.message = err;
    }

    ctx.body = rs;
});

router.get('/:env/statistics/submits', async (ctx, next) => {
    ctx.body = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.SubmitStatistics, null, null, 'CapitaWorkflowCenter');
});

router.post('/:env/statistics/submitDetails', async (ctx, next) => {
    let so = ctx.request.body;

    if ((so.groups || []).length > 0) {
        so.groups = so.groups.join(',') + ',';
    }

    so.wheres = '';

    if (so.leoOnly) {
        so.wheres = `and (B.ProcessGroupName like '%leo%' or B.ProcessGroupName='CLSA3.0')`;
    }

    if ((so.processGroups || []).length > 0) {
        so.wheres += ` and B.ProcessGroupId IN (${(so.processGroups.join(','))})`;
    } else {
        delete so.processGroups;
    }

    if (so.year && so.year != 'all') {
        so.wheres += ` and YEAR(b.ProcStartDate)=${so.year}`;
    }

    ctx.body = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.SubmitDetailsStatistics, so, null, 'CapitaWorkflowCenter');
});

router.get('/:env/statistics/audits', async (ctx, next) => {
    ctx.body = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.AuditStatistics, null, null, 'CapitaWorkflowCenter');
});

router.post('/:env/statistics/auditDetails', async (ctx, next) => {
    let so = ctx.request.body;

    if ((so.groups || []).length > 0) {
        so.groups = so.groups.join(',') + ',';
    }

    so.wheres = '';

    if (so.leoOnly) {
        so.wheres = `and (B.ProcessGroupName like '%leo%' or B.ProcessGroupName='CLSA3.0')`;
    }

    if ((so.processGroups || []).length > 0) {
        so.wheres += ` and B.ProcessGroupId IN (${so.processGroups.join(',')})`;
    } else {
        delete so.processGroups;
    }

    if (so.year && so.year != 'all') {
        so.wheres += ` and YEAR(b.LastApprovedDate)=${so.year}`;
    }

    ctx.body = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.AuditDetailsStatistics, so, null, 'CapitaWorkflowCenter');
});

router.get('/:env/workflow/details', async (ctx, next) => {
    let params = {
        serialNumber: ctx.request.query.serialNumber.trim()
    };

    let isNumber = /^\d+$/.test(params.serialNumber);

    let promiseInfo = ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForObject(
        script.GetBizCommonInfo, params,
        builder => {
            if (isNumber) {
                builder.and('a.ID=@serialNumber');
            } else {
                builder.and('a.SerialNumber=@serialNumber');
            }
        }, 'CapitaWorkflowCenter');

    let promiseWorklist = ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(
        script.GetWorklist, params,
        builder => {
            if (isNumber) {
                builder.and('a.BizFormID=@serialNumber');
            } else {
                builder.and('a.SerialNumber=@serialNumber');
            }
        }, 'CapitaWorkflowCenter');
    let promiseDestinations = ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(
        script.GetDestinationUsers, params,
        builder => {
            if (isNumber) {
                builder.and('b.ID=@serialNumber');
            } else {
                builder.and('b.SerialNumber=@serialNumber');
            }
        }, 'CapitaWorkflowCenter');
    let promiseLogs = ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(
        script.GetAuditingLogs, params,
        builder => {
            if (isNumber) {
                builder.and('b.ID=@serialNumber');
            } else {
                builder.and('b.SerialNumber=@serialNumber');
            }

            builder.asc('a.ID');
        }, 'CapitaWorkflowCenter');

    let rs = {
        at: dayjs().format("YYYY-MM-DD HH:mm:ss"),
        success: true
    };

    await Promise.all([promiseInfo, promiseWorklist, promiseDestinations, promiseLogs]).then(([common, worklists, destinationUsers, logs]) => {
        rs.common = common.data;
        rs.worklists = worklists.datas;
        rs.destinationUsers = destinationUsers.datas;
        rs.logs = logs.datas;
    }).catch(rease => {
        rs.message = rease;
        rs.success = false;
    });

    ctx.body = rs;
});

router.get('/:env/workflow/doaitems/:id', async (ctx, next) => {
    let params = {
        doaItemId: ctx.params.id
    };

    let doaDetail = await await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForObject(script.GetDoaItemDetail, params, 'CapitaWorkflowCenter');
    let doas = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.GetDOAItems, params, 'CapitaWorkflowCenter');

    ctx.body = {
        at: doas.at,
        success: doas.success && doaDetail.success,
        detail: doaDetail.data,
        items: doas.datas,
        total: doas.total
    };
});

router.post('/:env/workflow/apilog', async (ctx, next) => {
    let dbHelper = ctx.getDbHelper(`iWorkflow(${ctx.params.env})`);
    let values = ctx.request.body;

    if (values.ProcessGroupName.indexOf('CLSA') == 0) {
        values.controller = 'NCSA';
        values.action = 'UseSealedFormForAllBUTypeProcess';
    } else {
        values.controller = 'LeoBizCommon';
        values.action = 'LeoBizCommonProcess';
    }

    let datas = await dbHelper.queryForList(script.GetApiLog, values);

    ctx.body = datas;
});

router.post('/:env/workflow/doa', async (ctx, next) => {
    let host = (configs.hosts.find(h => h.env == ctx.params.env) || { url: '' }).url;

    let params = decodeURI(ctx.request.body.conditions);

    let queryString = '';
    let items = params.split('&');

    items.forEach(i => {
        let arr = i.split('=');

        if (arr[0]) {
            if (arr[0] == 'isShowAll') {
                queryString += `${arr[0]}=true&`
            } else {
                queryString += `${arr[0]}=${urlencode(arr[1] || '')}&`
            }
        }
    });

    let url = `${host}/api/DOA/GetDoa?AppID=${configs.auth.appId}&AppSecret=${configs.auth.appSecret}&${queryString}`;

    let response = await axios({
        method: 'get',
        headers: { 'content-type': 'application/x-www-form-urlencoded', 'Cache-Control': 'no-cache' },
        url: url,
        responseType: 'application/json',
        httpsAgent: new https.Agent({
            rejectUnauthorized: false
        })
    });

    ctx.body = response.data;
});

router.post('/:env/workflow/pageAccess', async (ctx, next) => {
    let values = {
        serialNumbers: ctx.request.body
    };

    let rs = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`).queryForList(script.GetPageAccesses, values, 'CapitaWorkflowCenter');

    ctx.body = rs;
});

router.post('/:env/statistics/pageloads', async (ctx, next) => {
    let paged = Object.assign({}, { pageIndex: 1, pageSize: 20 }, ctx.request.body);

    let rs = await ctx.getDbHelper(`iWorkflow(${ctx.params.env})`)
        .queryForList(script.PageAccessStatistics, paged, b => b.paging(), 'CapitaWorkflowCenter')

    ctx.body = rs;
});

let getApiConfig = (api) => {
    return configs.apis.find(item => item.url.toLowerCase() == (api || '').toLowerCase());
};

let resolveParams = (data) => {
    let params = '';

    if (data) {
        for (let p of data) {
            if (p.type == 'query') {
                params += `&${p.name}=${p.value}`;
            }
        }
    }

    return params;
}

let resolveBody = (data) => {
    let params = '';

    if (data) {
        for (let p of data) {
            if (p.type == 'body') {
                params += `&${p.name}=${p.value}`;
            }
        }
    }

    return params;
}

module.exports = router;